#include "player.h"
#include "frame.h"
#include "player_bonus.h"
#include "turn.h"
#include "frame_behaviour.h"
#include "frame_controller.h"

#define FRAME_COUNT 10


Player::Player(const std::string& name)
:   _name(name)
{
    //_frames.push_back(std::make_shared<Frame>());
}
        
std::string Player::getName() const
{
    return _name;
}
    
std::vector<std::shared_ptr<Frame>>::iterator Player::getFirstOpenFrameIter()
{
//  return std::find_if( _frames.begin(), _frames.end(), std::bind(&Player::check, this, _1) );
    return std::find_if( _frames.begin(), _frames.end(), [](const std::shared_ptr<Frame>& f) { return f->isOpened(); } );
}

void Player::makeTurn(const PinScheme& scheme)//(Turn& turn)
{
    //std::cout << _name << " knocked " << scheme.getMarkedCount() << std::endl;
    
//    std::cout << "_frames.empty() == " << _frames.empty() << std::endl;       
//    scheme.print();
    
    //PinScheme scheme = scheme_;
    //std::cout << "_frames.back()->isDone() == " << _frames.back()->isDone() << std::endl;

    if (_frames.empty() || _frames.back()->isDone())
    {
        if (_frames.size() == FRAME_COUNT - 1)
        {
            // maybe need to use std::unique_ptr instead of std::shared_ptr
            _frames.push_back(std::make_shared<Frame>(std::make_shared<FrameBehaviourLast>()));
        }
        else
        {
            _frames.push_back(std::make_shared<Frame>());
        }
        /*
        auto f = boost::bind(&Player::updateFrameRes, this, _1);        
        FrameController::getInstance().onUpdateFrame( f );        
        FrameController::getInstance().updateFrameReq();
        */
        std::cout << "update frame ... " << std::endl;
        FrameController::getInstance().updateFrameReq();
    }
    
    auto currFrame = _frames.back();

    
//    std::cout << "try to knock " << scheme.getMarkedCount() << std::endl;
    Frame::Bonus turnBonus = currFrame->fire(scheme);
    
    
   // std::cout << "scores now are " << getScores() << std::endl;
    
    if (turnBonus == Frame::Bonus::STRIKE)
    {
    
    }
    
    auto it = _frames.begin();//getFirstOpenFrameIter();
    size_t len = _frames.size() - 1;
    //for (; it != _frames.end(); ++it)
    for (size_t i = 0; i < len; ++i)
    {
        //std::cout << "------------------- cast something" << std::endl;
        _frames.at(i)->castSpecials();
    }
    
//    std::cout << "and now are " << getScores() << std::endl;
        
//    if (currFrame->isDone())
//    {
//        _frames.push_back(std::make_shared<Frame>());
//    }
}

bool Player::isFrameDone() const
{
    return _frames.empty() ? false : _frames.back()->isDone();
}

int Player::getScores() const
{
    int scores = 0;
    for (auto& frame : _frames)
    {
        scores += frame->getScores();
    }
    return scores;
}

void Player::printScores() const
{
    //std::cout << "frameCount: " << _frames.size() << std::endl;

    std::cout << _name << ": " << std::endl;
    int i = 1;
    for (auto& frame : _frames)
    {
        std::cout << "frame " << i << "; scores: " << frame->getScores() << std::endl;
        ++i;
    }
}